package com.zl.aop.advice;

import com.zl.aop.UserService;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

import java.sql.SQLException;
import java.util.Arrays;

/**
 * 日志增强类
 * @ClassName: LogAdvice
 * @author: suke
 * @since: 2021/8/2 17:14
 */
@Component
@Aspect   //表示该类是一个通知类
public class LogAdvice {
    private static final Logger log =Logger.getLogger(UserService.class);

    /**
     * 前置增强
     *   JoinPoint: 连接点(被代理类的中的方法)
     *     jp.getTarget()  获取被代理类的对象
     *     jp.getSignature()  获取方法的签名:  getName() 获取方法名
     *     jp.getArgs()  调用目标方法的参数
     * @param jp
     */
    @Before("execution(* com.zl.aop.impl..*.*(..))")
    public void before(JoinPoint jp){
        log.info("调用"+jp.getTarget()+"的"+jp.getSignature().getName()
                +"方法,传递的参数:"+ Arrays.toString(jp.getArgs()));
    }

    /**
     * 后置增强
     * @param jp
     * @param result  返回值  接收目标方法的返回值结果
     */
    @AfterReturning(pointcut = "execution(* com.zl.aop.impl..*.*(..))",returning = "result")
    public void afterReturning(JoinPoint jp,Object result){
        log.info("调用"+jp.getTarget()+"的"+jp.getSignature().getName()
                +"方法,方法的返回值:"+result);
    }

    /**
     * 异常增强
     * @param jp
     * @param e 增强的异常类型
     */
    public void afterThrowing(JoinPoint jp,Exception e){
        log.error("调用"+jp.getTarget()+"的"+jp.getSignature().getName()
                +"方法发生异常"+e);
    }

    /**
     * 最终增强
     * @param jp
     */
    public void after(JoinPoint jp){
        log.info(jp.getSignature().getName()+"方法执行结束");
    }

    /**
     * 环绕增强
     * @param jp
     * @throws Throwable
     */

    public Object aroundLogger(ProceedingJoinPoint jp) throws Throwable {
        log.info(jp.getSignature().getName() + "方法开始执行");
        try {
            //执行目标方法
            Object rs = jp.proceed();
            log.info(jp.getSignature().getName() + "方法正常执行完");
            return rs;
        } catch (SQLException e) {
            log.error("调用" + jp.getTarget() + "的" + jp.getSignature().getName()
                    + "方法发生异常" + e);
            throw e;
        } finally {
            log.info(jp.getSignature().getName() + "执行完了");
        }

    }

}
